package com.smartsaas.ugclivii.cd;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import com.smartsaas.ugclivii.entity.BomConfig;
import com.smartsaas.ugclivii.enums.CsysType;
import com.smartsaas.ugclivii.job.JobUtils;
import com.smartsaas.ugclivii.ui.UiContext;
import com.smartsaas.ugclivii.utils.FunUtils;
import nxopen.*;
import nxopen.blockstyler.BodyCollector;
import nxopen.blockstyler.Node;
import nxopen.blockstyler.Tree;
import nxopen.blockstyler.TreeListMenu;
import nxopen.features.Feature;
import nxopen.uf.*;

import java.rmi.RemoteException;
import java.util.*;
import java.util.stream.Collectors;

import static nxopen.uf.UFConstants.UF_MODL_CYLINDRICAL_FACE;

public class BomTreeHandler implements Tree.OnEndLabelEditCallback, Tree.OnBeginLabelEditCallback, Tree.AskEditControlCallback, Tree.OnEditOptionSelectedCallback, Tree.OnStateChangeCallback, Tree.OnMenuCallback, Tree.OnMenuSelectionCallback, Tree.OnSelectCallback {
    private static Node CURRENT_NODE;
    private static Body CURRENT_BODY;

    @Override
    public Tree.ControlType askEditControlCallback(Tree tree, Node node, int i) throws NXException, RemoteException {
        if (i>1&&i<5){
            Map<String, List<BomConfig>> bomConfig = UiContext.getInstance().getBomConfig();
            if (CollectionUtil.isNotEmpty(bomConfig)){
                if (i==2){
                    Set<String> key = bomConfig.keySet();
                    tree.setEditOptions(ArrayUtil.toArray(key, String.class),0);
                }
                if (i==3){
                    String text = node.getColumnDisplayText(2);
                    List<BomConfig> bomConfigs = bomConfig.get(text);
                    if (CollectionUtil.isNotEmpty(bomConfigs)){
                        List<String> names = bomConfigs.stream().map(BomConfig::getName).collect(Collectors.toList());
                        tree.setEditOptions(ArrayUtil.toArray(names, String.class),0);
                    }
                }
                if (i==4){
                    String[] op={"车床","采购","附图","库存"};
                    tree.setEditOptions(op,0);
                }
            }
            return Tree.ControlType.COMBO_BOX;
        }
        return Tree.ControlType.NONE;
    }

    @Override
    public Tree.BeginLabelEditState onBeginLabelEditCallback(Tree tree, Node node, int i) throws NXException, RemoteException {
        if (i==6||i==7||i==1){
            return Tree.BeginLabelEditState.ALLOW;
        }
        return Tree.BeginLabelEditState.DISALLOW;
    }

    @Override
    public Tree.EditControlOption onEditOptionSelectedCallback(Tree tree, Node node, int i, int i1, String s, Tree.ControlType controlType) throws NXException, RemoteException {
        try {
            if (i==3){
                String bigKey = node.getColumnDisplayText(2);
                String smallKey = node.getColumnDisplayText(3);
                List<BomConfig> bomConfigList = UiContext.getInstance().getBomConfig().get(bigKey);
                for (BomConfig bomConfig : bomConfigList) {
                    if(bomConfig.getName().equals(smallKey)){
                        // 坐标系类型 1 wcs 2 自动坐标系 3 绝对坐标系
                        Integer csysCode = bomConfig.getCsys();
                        String csys = CsysType.getByCode(csysCode);
                        node.setColumnDisplayText(5,csys);
                        if (csysCode==1||csysCode==3){
                            //运算赋值
                            JobUtils.doJob("运算赋值",()->JobUtils.bomCalculatedSize(tree,node,csysCode,bomConfig));
                        }
                    }
                }
            }

        }catch (Exception e){

        }
        return Tree.EditControlOption.ACCEPT;
    }

    @Override
    public Tree.EndLabelEditState onEndLabelEditCallback(Tree tree, Node node, int i, String s) throws NXException, RemoteException {
        return Tree.EndLabelEditState.ACCEPT_TEXT;
    }

    @Override
    public void onMenuCallback(Tree tree, Node node, int i) throws NXException, RemoteException {
        if(node!=null){
            TreeListMenu menu = tree.createMenu();
            menu.addMenuItem(0,"删除节点","delete");
            tree.setMenu(menu);
        }
    }

    @Override
    public void onMenuSelectionCallback(Tree tree, Node node, int i) throws NXException, RemoteException {
        if (node!=null){
            tree.deleteNode(node);
        }
    }

    @Override
    public void onSelectCallback(Tree tree, Node node, int i, boolean b) throws NXException, RemoteException {
        if (b){
            JobUtils.doJob("选择BOM",()->{
                selectBody(node);
            });
        }
    }

    @Override
    public void onStateChangeCallback(Tree tree, Node node, int i) throws NXException, RemoteException {
        int state = node.getState()==1?2:1;
        node.setState(state);
    }

    public static void selectBody(Node node) {
        try {
            String tag = node.getColumnDisplayText(8);
            BodyCollection bodies = UiContext.SESSION.parts().work().bodies();
            TaggedObjectCollection.Iterator iterator = bodies.iterator();
            UFView ufView = UiContext.UF_SESSION.view();
            BodyCollector bomSelection = UiContext.getInstance().getBomSelection();
            TaggedObject[] objects = bomSelection.getSelectedObjects();
            while (iterator.hasNext()){
                Body next = (Body)iterator.next();
                if (String.valueOf(next.tag().value).equals(tag)){
                    next.unhighlight();
                    next.unblank();
                    CURRENT_BODY=next;
                    CURRENT_NODE=node;
                }else {
                    next.blank();
                }
            }
            if (CURRENT_BODY!=null){
                List<Body> sameBody = FunUtils.findSameBody(CURRENT_BODY, objects);
                for (Body body : sameBody) {
                    body.unhighlight();
                    body.unblank();
                }
                ufView.fitView(Tag.NULL, 0.8f);
            }
        }catch (Exception e){
            UiContext.getInstance().debug(e);
        }
    }
    public static void getBodyDistances(Tree tree, Node node, Integer csysCode, BomConfig bomConfig){
        //量尺逻辑
        synchronized (BomTreeHandler.class){
            try {
                Part work = UiContext.SESSION.parts().work();
                UFModeling modeling = UiContext.UF_SESSION.modeling();
                if (CURRENT_NODE!=null&&CURRENT_BODY!=null){
                    //方体
                    if(bomConfig.getBlkOrCyl()==1){
                        Tag scyc = getScyc(csysCode);
                        double[] distances = FunUtils.getBodyDistances(scyc, CURRENT_BODY);
                        if (distances!=null){
                            node.setColumnDisplayText(6,Math.round(distances[0])+"x"+Math.round(distances[1])+"x"+Math.round(distances[2]) );
                        }
                    }
                    if (bomConfig.getBlkOrCyl()==2){
                        //圆体
                        Face[] faces = CURRENT_BODY.getFaces();
                        List<Integer> dl=new ArrayList<>();
                        List<Integer> ll=new ArrayList<>();
                        for (Face face : faces) {
                            Face.FaceType faceType = face.solidFaceType();
                            if (faceType.equals(Face.FaceType.CYLINDRICAL)){
                                face.highlight();
                                UFModeling.AskFaceData askFaceData = modeling.askFaceData(face.tag());
                                double radius = askFaceData.radius;
                                UiContext.getInstance().debug("柱面半径:"+radius);
                                dl.add(Math.round((float) radius)*2);
                                try {
                                    //计算深度
                                    Edge[] edges = face.getEdges();
                                    List<Point3d> point3ds=new ArrayList<>();
                                    for (Edge edge : edges) {
                                        Section section = work.sections().createSection(edge);
                                        Arc curve =(Arc) work.curves().createSmartCompositeCurve(section, SmartObject.UpdateOption.WITHIN_MODELING, 0.001);
                                        point3ds.add(curve.centerPoint());
                                    }
                                    double a = Math.pow(point3ds.get(0).x - point3ds.get(1).x, 2) + Math.pow(point3ds.get(0).y - point3ds.get(1).y, 2) + Math.pow(point3ds.get(0).z - point3ds.get(1).z, 2);
                                    double dis = Math.sqrt(a);
                                    UiContext.getInstance().debug("柱面长度:"+dis);
                                    ll.add(Math.round((float) dis));
                                }catch (Exception e){
                                    UiContext.getInstance().debug("柱面长度:计算错误");
                                    ll.add(-1);
                                }
                            }
                        }
                        dl.sort((o1, o2) -> o2-o1);
                        ll.sort((o1, o2) -> o2-o1);
                        String pro = bomConfig.getPro();
                        String f="";
                        if (pro.contains("<D>")){
                            f=pro.replace("<D>",dl.get(0)+"");
                        }
                        if (pro.contains("<D1>")){
                            f=pro.replace("<D1>",dl.get(0)+"");
                        }
                        if (pro.contains("<D2>")){
                            f=pro.replace("<D2>",dl.get(1)+"");
                        }
                        if (pro.contains("<D3>")){
                            f=pro.replace("<D3>",dl.get(2)+"");
                        }
                        if (pro.contains("<L>")){
                            f=f.replace("<L>",ll.get(0)+"");
                        }
                        if (pro.contains("<L1>")){
                            f=f.replace("<L1>",ll.get(0)+"");
                        }
                        if (pro.contains("<L2>")){
                            f=f.replace("<L2>",ll.get(1)+"");
                        }
                        if (pro.contains("<L3>")){
                            f=f.replace("<L3>",ll.get(2)+"");
                        }
                        node.setColumnDisplayText(6,f);
                    }
                }
                CURRENT_NODE=null;
                CURRENT_BODY=null;
            }
            catch (Exception e){
                UiContext.getInstance().debug(e);
            }
        }
    }

    public static Tag getScyc(Integer csysCode) throws RemoteException, NXException {
        UFCsys csys = UiContext.UF_SESSION.csys();
        if (csysCode==1){
            //工作坐标系
            return csys.askWcs();
        }else{
            //绝对坐标系
            double[] origin={0,0,0};
            double[] adsMtx={1,0,0, 0,1,0, 0,0,1};
            Tag matrix = csys.createMatrix(adsMtx);
            return csys.createTempCsys(origin, matrix);
        }
    }
}
